﻿#ifndef QTSOCKET_TCPCLIENT_H
#define QTSOCKET_TCPCLIENT_H

#include <QHostAddress>
#include "qnet_global.h"

class QTimerEvent;
class QTcpSocket;

QNET_NAMESPACE_BEGIN

class TcpSession;
class ISessionListener;

/**
 * @brief The TcpClient class  表示tcp的客户端。
 */
class QNETSHARED_EXPORT TcpClient : public QObject
{
    Q_OBJECT
public:
    explicit TcpClient(ISessionListener *listener, QObject *parent = nullptr);
    virtual ~TcpClient() override;
public:
    /**
     * @brief reconnect 重新连接。
     */
    void reconnect();
    /**
    * @brief connect 连接指定主机。
    * @param ip 主机地址。
    * @param port 主机端口。
    */
    void connect(QHostAddress ip, quint16 port);
    /**
     * @brief bind 绑定本机端口。
     * @param ip 本地地址。
     * @param port 本地端口。
     * @return 成功返回true。
     */
    bool bind(QHostAddress ip,quint16 port);
    /**
     * @brief autoReconnect 获取是否自动重连。
     * @return
     */
    bool autoReconnect() const;
    void setAutoReconnect(bool autoReconnect);
    /**
     * @brief localAddr 本地监听地址。
     * @return
     */
    QHostAddress localAddr() const;

    /**
     * @brief remoteAddr 远端地址。
     * @return
     */
    QHostAddress remoteAddr() const;

    /**
     * @brief localPort 本地端口。
     * @return
     */
    quint16 localPort() const;

    /**
     * @brief remotePort 远端端口。
     * @return
     */
    quint16 remotePort() const;

    /**
     * @brief destory 销毁客户端。
     */
    void destory();
    /**
     * @brief setListener 设置监听者。
     * @param listener 监听者实例，可为空。
     */
    void setListener(ISessionListener *listener);
protected:
    void timerEvent(QTimerEvent *event) override;
public slots:
    /**
     * @brief disconnect 断开连接。
     */
    void disconnected();
    /**
     * @brief connected 已连接。
     */
    void connected();
    /**
     * @brief stateChanged 状态改变信号。
     * @param state
     */
    void stateChanged(QAbstractSocket::SocketState state);

    /**
     * @brief error 错误信息。
     */
    void error(QAbstractSocket::SocketError error);
private:
    /**
     * @brief startReconnectTimer 启动重连Timer。
     * @return 成功启动返回true。
     */
    bool startReconnectTimer();
    /**
     * @brief stopReconnectTimer 关闭重连Timer。
     */
    void stopReconnectTimer();

    /**
     * @brief onSessionChange  状态改变通知。
     * @param connect 是否连接。
     */
    void onSessionChange(bool connect);
private:
    QTcpSocket *m_socket;//写数据对象
    QHostAddress m_localAddr;
    QHostAddress m_remoteAddr;
    quint16 m_localPort;
    quint16 m_remotePort;

    TcpSession *m_session;
    int m_timerID;
    bool m_autoReconnect; //是否自动重连。
    int m_reconnectSpan; // 重连间隔（毫秒）
    ISessionListener *m_listener; // 会话监听器。
};
QNET_NAMESPACE_END

#endif // TCPCLIENT_H
